import redis
from cacheout import Cache
import pandas as pd
import abc
from six import with_metaclass


class BaseCache(with_metaclass(abc.ABCMeta)):
    """
    缓存接口。
    """

    @abc.abstractmethod
    def get(self, key):
        """
        根据key获取数据
        :param key:
        :return:
        """
        raise NotImplementedError

    @abc.abstractmethod
    def set(self, key, value):
        """
        设置key对应的value
        注意，需要实现ttl过期时间设置，默认为0
        :param key:
        :return:
        """
        raise NotImplementedError

    @abc.abstractmethod
    def get_cache(self, ttl):
        """
        获取缓存接口对象，并设置ttl
        :return:
        """
        raise NotImplementedError


class DefaultCache(BaseCache):
    cache = None

    def __init__(self, ttl=0):
        if DefaultCache.cache is None:
            DefaultCache.cache = Cache()
        self.ttl = ttl

    def get(self, key):
        return self.cache.get(key)

    def set(self, key, value):
        self.cache.set(key, value, ttl=self.ttl)

    def get_cache(self, ttl):
        return DefaultCache(ttl)


class RedisCache(BaseCache):
    cache = None

    def __init__(self, ttl=None, config=None):
        if RedisCache.cache is None:
            pwd = config.password if 'password' in config.keys() else None
            # host是redis主机，需要redis服务端和客户端都起着 redis默认端口是6379
            pool = redis.ConnectionPool(host=config.host, port=6379, db=config.db,
                                        decode_responses=False,password=pwd)
            RedisCache.cache = redis.Redis(connection_pool=pool)
        self.ttl = ttl

    def get(self, key):
        df = self.cache.get(key)
        if df is not None:
            return pd.read_msgpack(df)
        else:
            return df

    def set(self, key, value):
        """
        value为Dataframe
        :param key:
        :param value:
        :return:
        """

        self.cache.set(key, value.to_msgpack(compress='zlib'), ex=self.ttl)

    def get_cache(self, ttl):
        return RedisCache(ttl)


class CacheKit(object):
    cache = DefaultCache()
